package com.haizhi.crm.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.haizhi.crm.biz.builder.MsgSearchQoBuilder;
import com.haizhi.crm.biz.constant.AccountType;
import com.haizhi.crm.biz.constant.CompanyBasicType;
import com.haizhi.crm.biz.dao.ConcernedDao;
import com.haizhi.crm.biz.dao.FavouriteDao;
import com.haizhi.crm.biz.model.*;
import com.haizhi.crm.biz.service.CompanyService;
import com.haizhi.crm.biz.service.HistoryViewService;
import com.haizhi.crm.biz.util.MessageUtil;
import com.haizhi.crm.common.constant.BizStatus;
import com.haizhi.crm.common.constant.CrmConstant;
import com.haizhi.crm.common.constant.CrmSchema;
import com.haizhi.crm.common.constant.EsOperator;
import com.haizhi.crm.common.context.SpringContext;
import com.haizhi.crm.common.exception.UnexpectedStatusException;
import com.haizhi.crm.common.json.JSONUtils;
import com.haizhi.crm.common.log.GLog;
import com.haizhi.crm.common.model.PageResponse;
import com.haizhi.crm.common.model.Response;
import com.haizhi.crm.common.rest.RestService;
import com.haizhi.crm.common.util.ApplicationUtils;
import com.haizhi.crm.common.util.CommonUtils;
import com.haizhi.crm.common.util.Getter;
import com.haizhi.crm.search.builder.SearchQoBuilder;
import com.haizhi.crm.search.model.SearchQo;
import com.haizhi.crm.search.model.SearchResp;
import com.haizhi.crm.search.model.SearchVo;
import com.haizhi.crm.search.service.SearchService;
import com.haizhi.crm.sys.auth.dao.DepartmentDao;
import com.haizhi.crm.sys.auth.dao.RelationItemDao;
import com.haizhi.crm.sys.auth.dao.UserDao;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * Created by haizhi on 2018/3/6.
 */
@Service
public class CompanyServiceImpl implements CompanyService {

    private static final GLog LOG = new GLog(CompanyService.class);

    @Autowired
    private RestService httpSender;

    @Autowired
    private SearchService searchService;

    @Autowired
    private DepartmentDao departmentDao;

    @Autowired
    private ConcernedDao concernedDao;

    @Autowired
    private UserDao userDao;

    @Autowired
    private FavouriteDao favouriteDao;

    @Autowired
    private HistoryViewService historyViewService;
    @Autowired
    private RelationItemDao relationItemDao;


    public Object getRelationship(RelationshipQo relationshipQo) throws Exception {

        GraphConfig param = SpringContext.getBean(GraphConfig.class);
        param.addNode(relationshipQo.getEntityType());
        param.addEdgeList(relationshipQo.getGraphTypeList());
        param.addVertex(relationshipQo.getEntityType(), relationshipQo.getId());

        LOG.info(JSON.toJSON(param));

        String resp = this.httpSender.doPost(ApplicationUtils.getGraphUri(), param, String.class);
        return JSON.parseObject(resp);
    }

    public Response findProductSigns(CompanyProductSignQo companyStartServiceQo) {
        SearchQoBuilder searchQoBuilder = new SearchQoBuilder();
        String companyKey = companyStartServiceQo.getCompanyKey();
        String productName = companyStartServiceQo.getProductName();
        String detailType = companyStartServiceQo.getDetailType();
        Integer pageNo = companyStartServiceQo.getPageNo();
        Integer pageSize = companyStartServiceQo.getPageSize();

        searchQoBuilder.setGraph(CrmSchema.CRM);
        searchQoBuilder.addSchemas(CrmSchema.ACCOUNT);
        searchQoBuilder.setPageSize(pageSize);
        searchQoBuilder.setPageNo(pageNo);
        searchQoBuilder.addTermFilter("customer_key", companyKey);

        if (StringUtils.isNotBlank(productName)) {
            searchQoBuilder.setKeyword(productName);
            searchQoBuilder.addMatchQuery("product_name" );
        }
        searchQoBuilder.addTermFilter("product_type", detailType);
        SearchResp searchResp = searchService.search(searchQoBuilder.get()).getSearchResp();
        long total = searchResp.getTotal();
        return new PageResponse(searchResp.getData(), total, pageNo, pageSize);
    }

    public Object getBasic(String id, CompanyBasicType companyBasicType) throws Exception {
        SearchQo searchQo = MsgSearchQoBuilder.get(CrmSchema.CRM, id);
        LOG.info(JSON.toJSON(searchQo));
        SearchVo searchVo = searchService.search(searchQo);
        List<Map<String, Object>> datas = JSONUtils.toListMap(searchVo.getSearchResp().getData());
        if (datas.size() == 0) {
            return null;
        }
        Map<String, Object> data = datas.get(0);
        String objectKey = Getter.get("object_key", data);
        historyViewService.save(CrmSchema.COMPANY, objectKey, Getter.get("name", data));

        List<ConcernedDo> concernedDos = concernedDao.findByCompanyKeyAndUserId(objectKey, CommonUtils.getUserID());
        data.put("concerned", CollectionUtils.isEmpty(concernedDos) ? false : true);

        return data;
    }


    /**
     * 查询公司
     *
     * @param companyKeys 逗号分割的company Key
     * @return
     */
    public List<CompanyVo> queryCompanysByKeys(String companyKeys) {

        if (StringUtils.isBlank(companyKeys)) {
            return null;
        }

        List<CompanyVo> companyList = new ArrayList<CompanyVo>();
        String[] companyKeysArr = companyKeys.split("," );
        CompanyVo company;
        for (String companyKey : companyKeysArr) {
            company = this.queryCompanyByKey(companyKey);
            if (null != company) {
                companyList.add(company);
            }
        }

        return companyList;
    }

    /**
     * 查询公司
     *
     * @param companyKey
     * @return
     */
    public CompanyVo queryCompanyByKey(String companyKey) {

        if (StringUtils.isBlank(companyKey)) {
            return null;
        }

        CompanyVo company = null;

        return company;
    }

    /**
     * ES中查询客户信息
     *
     * @param customerKey
     * @return
     */
    public CompanyVo queryByCustomerKey(String customerKey) {
        SearchQoBuilder searchQoBuilder = new SearchQoBuilder();
        searchQoBuilder.setGraph(CrmSchema.CRM);
        searchQoBuilder.addSchemas(CrmSchema.COMPANY);
        searchQoBuilder.addTermFilter("object_key", new String[]{customerKey});

        SearchVo searchVo = this.searchService.search(searchQoBuilder.get());
        List<Map<String, Object>> companys = JSONUtils.toListMap(searchVo.getSearchResp().getData());

        CompanyVo company = null;
        if (!CollectionUtils.isEmpty(companys)) {
            Map<String, Object> data = companys.get(0);
            company = buildCompanyVo(data);

        }
        return company;
    }

    private CompanyVo buildCompanyVo(Map<String, Object> data) {
        CompanyVo company = new CompanyVo();
        company.setObjectKey(Getter.get("object_key", data));
        company.setName(Getter.get("name", data));
        return company;
    }

    /**
     * ES中查询客户信息
     *
     * @param customerName
     * @return
     */
    public Response findByName(String customerName) {
        try {
            //封装查询参数
            SearchQoBuilder searchQoBuilder = new SearchQoBuilder();
            searchQoBuilder.setKeyword(customerName);
            searchQoBuilder.setGraph(CrmSchema.CRM);
            searchQoBuilder.addSchemas(CrmSchema.COMPANY);
            searchQoBuilder.addMatchQuery("name" );
            Pair<Integer, List<SearchCustomerRespVo>> pair = searchCustomers(searchQoBuilder.get());
            return new Response(pair.getSecond());
        } catch (Exception e) {
            throw new UnexpectedStatusException(BizStatus.CUSTOMER_QUERY_ERROR, e);
        }
    }

    /**
     * 查询company集合
     *
     * @param employeeNos 客户经理employeeNo集合
     * @return
     */
    public List<CompanyVo> queryCompanysByCustomerManagers(List<String> employeeNos) {

        if (null == employeeNos || employeeNos.size() <= 0) {
            return null;
        }

        //封装查询参数
        SearchQo searchReqDto = new SearchQo();

        //schema
        searchReqDto.addSchema(CrmSchema.COMPANY);

        //filter
        List<Map<String, Object>> filter = new ArrayList<>();

        /*管户客户经理*/
        Map<String, Object> map = new HashMap<>();
        map.put("type", EsOperator.TERM);
        map.put("field", CrmSchema.FIELD_COMPANY_CUSTOMER_MANAGER);
        map.put("values", employeeNos.toArray());
        filter.add(map);
        searchReqDto.setFilter(filter);

        //ES RCP查询
        List<CompanyVo> companyList = new ArrayList<>();
        SearchVo searchVo = this.searchService.search(searchReqDto);

        List<Map<String, Object>> companys = JSONUtils.toListMap(searchVo.getSearchResp().getData());
        for (Map<String, Object> data : companys) {
            companyList.add(buildCompanyVo(data));
        }
        return companyList;
    }


    /**
     * 到es搜索客户列表
     *
     * @return
     */
    public Response searchCustomers(SearchCustomerReqQo searchCustomerReqQo) {
        try {
            String customerType = searchCustomerReqQo.getCustomerType();
            String customerSource = searchCustomerReqQo.getCustomerSource();
            String customerName = searchCustomerReqQo.getCustomerName();
            String regDateOrder = searchCustomerReqQo.getRegDateOrder();
            String regAmountOrder = searchCustomerReqQo.getRegAmountOrder();
            Integer pageNo = searchCustomerReqQo.getPageNo();
            Integer pageSize = searchCustomerReqQo.getPageSize();
            Long deptId = departmentDao.findByManagerId(CommonUtils.getUserID());
            //如果登陆用户不是经理且选择的是我的下属客户,则返回空
            if ((null == deptId) && CrmConstant.QUERYTYPE_UNDERLING.equals(customerType)) {
                return new PageResponse(null, 0, pageNo, pageSize);
            }

            SearchQoBuilder searchQoBuilder = new SearchQoBuilder();
            searchQoBuilder.setGraph(CrmSchema.CRM);
            searchQoBuilder.addSchemas(CrmSchema.COMPANY);
            searchQoBuilder.setPageNo(pageNo);
            searchQoBuilder.setPageSize(pageSize);

            List<Long> userIds = new ArrayList<>();
            getUserIds(customerType, deptId, userIds);
            if (userIds.size() == 0) {
                return new PageResponse(null, 0, pageNo, pageSize);
            }
            Set<String> keys = new HashSet<>();
            getObjectKeys(customerSource, userIds, keys);
            if (keys.size() == 0) {
                return new PageResponse(null, 0, pageNo, pageSize);
            }

            searchCustomerBuild(searchQoBuilder, keys.toArray(), customerName, regDateOrder, regAmountOrder);

            Pair<Integer, List<SearchCustomerRespVo>> customerList = searchCustomers(searchQoBuilder.get());
            PageResponse responseWrapper = PageResponse.success();
            responseWrapper.setPayload(customerList.getSecond());
            responseWrapper.setPageInfo(customerList.getFirst(), pageNo, pageSize);
            return responseWrapper;
        } catch (Exception e) {
            throw new UnexpectedStatusException(BizStatus.CUSTOMER_QUERY_ERROR, e);
        }
    }

    private void getUserIds(String customerType, Long deptId, List<Long> userIds) {
        //查询类型-如果选择的是我的客户
        if (CrmConstant.QUERYTYPE_MY.equals(customerType)) {
            userIds.add(CommonUtils.getUserID());
        } else {//查询类型-选择我的下属客户
            List<Integer> userIdsTmp = userDao.findByDeptId(deptId);
            for (Integer id : userIdsTmp)
                userIds.add(id.longValue());
            userIds.remove(CommonUtils.getUserID());
        }
    }

    private void getObjectKeys(String customerSource, List<Long> userIds, Set<String> keys) {
        //来源选择我的
        if (CrmConstant.COMPANY_LIST_SOURCE_MY.equals(customerSource)) {
            keys.addAll(relationItemDao.findEntityKeys(userIds));
        } else if (CrmConstant.COMPANY_LIST_SOURCE_CONCERN.equals(customerSource)) {//来源选择我关注的
            List<String> concernedKeys = concernedDao.findByUserIds(userIds.toArray(new Long[userIds.size()]));
            keys.addAll(concernedKeys);
        } else {//全部来源
            List<String> relationKeys = relationItemDao.findEntityKeys(userIds);
            List<String> concernedKeys = concernedDao.findByUserIds(userIds.toArray(new Long[userIds.size()]));
            keys.addAll(relationKeys);
            keys.addAll(concernedKeys);
        }
    }

    @Override
    public Response advancedSearch(CompanyAdvancedSearchQo searchQo) {
        try {
            Integer pageNo = searchQo.getPageNo();
            Integer pageSize = searchQo.getPageSize();
            boolean isListCompany = searchQo.isListedCompany();

            SearchQoBuilder searchQoBuilder = new SearchQoBuilder();
            searchQoBuilder.setGraph(CrmSchema.CRM);
            searchQoBuilder.addSchemas(CrmSchema.COMPANY);
            searchQoBuilder.setPageNo(pageNo);
            searchQoBuilder.setPageSize(pageSize);
            searchQoBuilder.addTermFilter("is_customer", searchQo.isCustomer());
            searchQoBuilder.addRangeFilter("reg_date", searchQo.getRegDateFrom(), searchQo.getRegDateTo());
            searchQoBuilder.addRangeFilter("reg_capital", searchQo.getRegAmountFrom(), searchQo.getRegAmountTo());
            searchQoBuilder.addTermFilter("institution_type", searchQo.getInstitutionType());
            searchQoBuilder.addTermFilter("economic_type", searchQo.getEconomicType());
            searchQoBuilder.addTermFilter("reg_province", searchQo.getRegProvince());
            searchQoBuilder.addTermFilter("industry", searchQo.getIndustry());
            searchQoBuilder.addTermFilter("state", searchQo.getState());
            searchQoBuilder.addTermFilter("is_listed_company", isListCompany);

            searchQoBuilder.addSort("reg_date", searchQo.getRegDateOrder());
            searchQoBuilder.addSort("reg_capital", searchQo.getRegAmountOrder());
            Pair<Integer, List<SearchCustomerRespVo>> pairs = searchCustomers(searchQoBuilder.get());
            List<SearchCustomerRespVo> customerRespVos = pairs.getSecond();
            long total = pairs.getFirst();
            return new PageResponse(customerRespVos, total, pageNo, pageSize);
        } catch (Exception e) {
            throw new UnexpectedStatusException(BizStatus.CUSTOMER_QUERY_ERROR, e);
        }
    }

    @Override
    public Object getAccount(String companyKey, AccountType accountType) {
        SearchQoBuilder searchQoBuilder = new SearchQoBuilder();
        searchQoBuilder.setGraph(CrmSchema.CRM);
        searchQoBuilder.addSchemas(CrmSchema.ACCOUNT);
        searchQoBuilder.addTermFilter("company_key", companyKey);
        if (accountType != AccountType.ALL) {
            searchQoBuilder.addTermFilter("type_", accountType.getField());
        }
        SearchVo searchVo = searchService.search(searchQoBuilder.get());
        List<Map<String, String>> result = MessageUtil.toList(searchVo.getSearchResp().getData());
        if (result == null || result.size() == 0) {
            return null;
        }
        return result;
    }

    @Override
    public Object getTransfer(String accountNo) {
        SearchQoBuilder searchQoBuilder = new SearchQoBuilder();
        searchQoBuilder.setGraph(CrmSchema.CRM);
        searchQoBuilder.addSchemas(CrmSchema.TRANSFER);
        searchQoBuilder.addTermFilter("settle_account_no", accountNo);
        SearchVo searchVo = searchService.search(searchQoBuilder.get());
        List<Map<String, String>> result = MessageUtil.toList(searchVo.getSearchResp().getData());

        SearchQoBuilder searchQoBuilder1 = new SearchQoBuilder();
        searchQoBuilder1.setGraph(CrmSchema.CRM);
        searchQoBuilder1.addSchemas(CrmSchema.TRANSFER);
        searchQoBuilder1.addTermFilter("counterparty_account_no", accountNo);
        SearchVo searchVo1 = searchService.search(searchQoBuilder1.get());
        List<Map<String, String>> result1 = MessageUtil.toList(searchVo1.getSearchResp().getData());
        result.addAll(result1);
        if (result == null || result.size() == 0) {
            return null;
        }
        return result;
    }

    private Pair<Integer, List<SearchCustomerRespVo>> searchCustomers(SearchQo searchQo) {
        List<SearchCustomerRespVo> customerList = new ArrayList<>();
        SearchVo searchVo = this.searchService.search(searchQo);
        SearchResp searchResp = searchVo.getSearchResp();
        Object data = searchResp.getData();
        List<Map<String, Object>> dataList = JSONUtils.jsonToListMap(JSON.toJSONString(data));
        if (dataList != null)
            for (Map<String, Object> customer : dataList) {
                customerList.add(customerBeanConvert(customer));
            }
        Long total = searchResp.getTotal();
        return Pair.of(total.intValue(), customerList);
    }

    private SearchCustomerRespVo customerBeanConvert(Map<String, Object> jo) {
        SearchCustomerRespVo dto = new SearchCustomerRespVo();
        dto.setName(jo.get("name" ).toString());
        dto.setObjectKey(Getter.get("object_key", jo));
        dto.setLogoUri(jo.getOrDefault("logo_uri", "" ).toString());
        dto.setLegalRepresentative(jo.get("legal_representative" ).toString());
        dto.setRegAmount(jo.get("reg_capital" ).toString());
        dto.setRegDate(Getter.get("reg_date", jo));
        dto.setRegAddress(jo.get("reg_address" ).toString());
        dto.setInstitutionType(jo.get("institution_type" ).toString());
        dto.setManagementScope(jo.get("management_scope" ).toString());
        dto.setStockCode(jo.get("stock_code" ).toString());
        dto.setServiceScaleIndex(jo.get("service_scale_index" ).toString());
        dto.setMarginContributionIndex(jo.get("margin_contribution_index" ).toString());
        dto.setCoorperationLength(jo.get("coorperation_length" ).toString());
        dto.setCreditClass(jo.get("credit_class" ).toString());
        int favouriteCount = favouriteDao.findFavouriteCount(CommonUtils.getUserID(), CrmSchema.COMPANY, jo.get("object_key" ).toString());
        dto.setFavourited(favouriteCount >= 1 ? true : false);

        List<ConcernedDo> concernedDos = concernedDao.findByCompanyKeyAndUserId(Getter.get("object_key", jo), CommonUtils.getUserID());
        dto.setConcerned(CollectionUtils.isEmpty(concernedDos) ? false : true);
        dto.setCustomer(Boolean.parseBoolean(jo.get("is_customer" ).toString()));
        return dto;
    }


    private void searchCustomerBuild(SearchQoBuilder searchQoBuilder, Object[] objs, String customerName, String regDateOrder, String regAmountOrder) {
        searchQoBuilder.addTermFilter(CrmSchema.FIELD_OBJECT_KEY, objs);
        searchQoBuilder.setKeyword(customerName);
        searchQoBuilder.addMatchQuery("name" );
        if (regAmountOrder != null && regDateOrder == null) {
            searchQoBuilder.addSort("reg_capital", regAmountOrder);
        } else if (regAmountOrder == null && regDateOrder != null) {
            searchQoBuilder.addSort("reg_date", regDateOrder);
        } else {
            searchQoBuilder.addSort("reg_date", "desc" );
        }


    }
}
